package com.qunar.wan.service;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.qunar.wan.common_api.model.*;
import com.qunar.wan.common_api.model.enums.EvaluateStatus;
import com.qunar.wan.common_api.serializer.RowBounds;
import com.qunar.wan.common_api.service.ActivityService;
import com.qunar.wan.common_api.service.UserActivityService;
import com.qunar.wan.common_api.service.UserService;
import com.qunar.wan.common_api.service.mapper.UserActivityMapper;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * User: huiming.suo
 * Date: 13-11-27
 * Time: 下午3:55
 */

@Service("userActivityService")
public class UserActivityServiceImpl extends BaseServiceImpl<UserActivity, UserActivityMapper> implements UserActivityService {
    @Value("#{settings['each.better.score']}")
    private int betterScore = 0;
    @Value("#{settings['each.good.score']}")
    private int goodScore = 0;
    @Value("#{settings['each.bad.score']}")
    private int badScore = 0;
    @Value("#{settings['each.assessment.score']}")
    private int assessmentScore = 0;
    @Resource
    private ActivityService activityService;
    @Resource
    private UserService userService;

    /**
     * 将UserActivity转化为User
     */
    private Function<UserActivity, User> toUserFunction = new Function<UserActivity, User>() {
        @Override
        public User apply(UserActivity userActivity) {
            List<User> tempList = userService.selectByQuery(new Query().fill("id", userActivity.getUserId()));
            return tempList.isEmpty() ? null : tempList.get(0);
        }
    };

    /**
     * 将UserActivity转化为Activity
     */
    private Function<UserActivity, Activity> toActivityFunction = new Function<UserActivity, Activity>() {
        @Override
        public Activity apply(UserActivity userActivity) {
            List<Activity> tempList = activityService.selectByQuery(new Query().fill("id", userActivity.getActId()));
            return tempList.isEmpty() ? null : tempList.get(0);
        }
    };

    /**
     * 查找参加活动的用户，可分页
     */
    @Override
    public List<User> selectUsersByActId(int actId, RowBounds rowBounds) {
        List<UserActivity> list = selectByQuery(new Query().fill("actId", actId), rowBounds);
        return Lists.transform(list, toUserFunction);
    }

    /**
     * 查找参加活动的所有用户
     */
    @Override
    public List<User> selectUsersByActId(int actId) {
        List<UserActivity> list = selectByQuery(new Query().fill("actId", actId));
        return Lists.transform(list, toUserFunction);
    }

    /**
     * 查找用户参加的所有活动
     */
    @Override
    public List<Activity> selectActsByUserId(int userId, RowBounds rowBounds) {
        List<UserActivity> list = selectByQuery(new Query().fill("userId", userId), rowBounds);

        //将UserActivity转化为Activity
        return Lists.transform(list, toActivityFunction);
    }

    /**
     * 查找用户参加过的活动
     */
    @Override
    public List<Activity> selectParticipatedActsByUserId(int userId, RowBounds rowBounds) {
        List<UserActivity> list = selectByTimeQuery(new Query().fill("userId", userId).fill("nowTimePar", new Date()).addSort(new Sort("id", Sort.Order.DESC)), rowBounds);

        //将UserActivity转化为Activity
        return Lists.transform(list, toActivityFunction);
    }

    /**
     * 查找用户参加过的活动总数
     */
    @Override
    public int selectParticipatedActsCount(int userId) {
        List<UserActivity> list = selectByTimeQuery(new Query().fill("userId", userId).fill("nowTimePar", new Date()));
        return list.size();
    }

    /**
     * 查找用户报名没参加的活动
     */
    @Override
    public List<Activity> selectEnrollActsByUserId(int userId, RowBounds rowBounds) {
        List<UserActivity> list = selectByTimeQuery(new Query().fill("userId", userId).fill("nowTimeEnr", new Date()).addSort(new Sort("id", Sort.Order.DESC)), rowBounds);

        //将UserActivity转化为Activity
        return Lists.transform(list, toActivityFunction);
    }

    /**
     * 判断用户是否报名了活动
     */
    @Override
    public boolean isUserEnroll(int userId, int actId) {
        return selectByUserIdActId(userId, actId) != null;
    }


    @Override
    public int getActPartyNum(int actId) {
        return selectUsersByActId(actId).size();
    }

    @Override
    public EvaluateStatus getUserEvaluateStatus(int userId, int actId) {
        List<UserActivity> list = selectByQuery(new Query().fill("actId", actId).fill("userId", userId));
        Preconditions.checkNotNull(list);
        EvaluateStatus es = list.get(0).getEvaluateStatus();
        return EvaluateStatus.codeOf(es.getCode());
    }

    @Override
    public UserActivity selectByUserIdActId(int userId, int actId) {
        List<UserActivity> list = selectByQuery(new Query().fill("actId", actId).fill("userId", userId));
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<UserActivity> selectByTimeQuery(Query query, RowBounds rowBounds) {
        return getMapper().selectByTimeQuery(query, rowBounds);

    }

    @Override
    public List<UserActivity> selectByTimeQuery(Query query) {
        return getMapper().selectByTimeQuery(query);
    }

    @Override
    @Transactional
    public boolean signUp(int activityId, int userId) {
        Activity activity = checkNotNull(activityService.selectById(activityId));
        User user = userService.selectUserById(userId);

        if (null != activity.getDeadline() && new DateTime().isAfter(activity.getDeadline().getTime())) {
            logger.info("{}报名参加\"{}\"失败:超过报名截止日期", user.getUserName(), activity.getTitle());
            return false;
        }
        if (isUserEnroll(userId, activityId)) {
            logger.info("{}报名参加\"{}\"失败:已经报名参加该活动", user.getUserName(), activity.getTitle());
            return false;
        }
        //if num <=0 mean  no people num limit
        if (activity.getPeopleLimit() > 0 && getActPartyNum(activityId) >= activity.getPeopleLimit()) {
            logger.info("{}报名参加\"{}\"失败:超过报名的人数限制", user.getUserName(), activity.getTitle());
            return false;
        }
        activity.setPeopleNum(activity.getPeopleNum() + 1);
        //update peopleNum
        activityService.updateObj(activity);
        // insert useractivity
        insertObj(new UserActivity(userId, activityId));
        return true;
    }

    @Override
    @Transactional
    public String assess(Activity activity, EvaluateStatus evaluateStatus, User assessmentor) {
        checkNotNull(activity);
        checkNotNull(assessmentor);
        UserActivity userActivity = selectByUserIdActId(assessmentor.getId(), activity.getId());
        String response = "";

        if (userActivity == null) {
            response = String.format("用户%s未参加活动,不能评价", assessmentor.getUserName());
            logger.info("用户{}未报名参加活动\"{}\",不能评价", assessmentor.getUserName(), activity.getTitle());
            return response;
        }
        if (userActivity.getEvaluateStatus() != EvaluateStatus.NOT) {
            response = String.format("用户%s已经评价过该活动:%s", assessmentor.getUserName(), userActivity.getEvaluateStatus().getMean());
            logger.info("用户{}已经评价过活动\"{}\"", assessmentor.getUserName(), activity.getTitle());
            return response;
        }
        logger.info("{}开始评价{}：{}", assessmentor.getUserName(), activity.getTitle(), evaluateStatus.getMean());

        /**更改活动状态,根据影响行数防止同一用户并发访问该请求*/
        userActivity.setEvaluateStatus(evaluateStatus);
        int affected = updateObj(userActivity);
        if (affected == 0) {
            return "系统繁忙";
        }


        /***评价人加分*/
        userService.addUserScore(assessmentor.getId(), assessmentScore);

        /***活动跟发起人加分*/
        int originScore = activity.getScore();
        if (evaluateStatus == EvaluateStatus.BAD) {
            activity.setBad(activity.getBad() + 1);
            activity.setScore(originScore + badScore);
            userService.addUserScore(activity.getUserId(), badScore);
        } else if (evaluateStatus == EvaluateStatus.BETTER) {
            activity.setBetter(activity.getBetter() + 1);
            activity.setScore(originScore + betterScore);
            userService.addUserScore(activity.getUserId(), betterScore);
        } else {
            activity.setGood(activity.getGood() + 1);
            activity.setScore(originScore + goodScore);
            userService.addUserScore(activity.getUserId(), goodScore);
        }
        activityService.updateObj(activity);
        return "success";
    }

}
